home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus Leser 15 / Amiga Plus Leser CD 15.iso / Tools / Development / MosaicSRC / libwww2 / Unused / HTAAServ.c < prev    next >
Encoding:
C/C++ Source or Header  |  2002-03-13  |  15.7 KB  |  612 lines

  1.  
  2. /* MODULE                            HTAAServ.c
  3. **        SERVER SIDE ACCESS AUTHORIZATION MODULE
  4. **
  5. **    Contains the means for checking the user access
  6. **    authorization for a file.
  7. **
  8. ** IMPORTANT:
  9. **    Routines in this module use dynamic allocation, but free
  10. **    automatically all the memory reserved by them.
  11. **
  12. **    Therefore the caller never has to (and never should)
  13. **    free() any object returned by these functions.
  14. **
  15. **    Therefore also all the strings returned by this package
  16. **    are only valid until the next call to the same function
  17. **    is made. This approach is selected, because of the nature
  18. **    of access authorization: no string returned by the package
  19. **    needs to be valid longer than until the next call.
  20. **
  21. **    This also makes it easy to plug the AA package in:
  22. **    you don't have to ponder whether to free() something
  23. **    here or is it done somewhere else (because it is always
  24. **    done somewhere else).
  25. **
  26. **    The strings that the package needs to store are copied
  27. **    so the original strings given as parameters to AA
  28. **    functions may be freed or modified with no side effects.
  29. **
  30. **    The AA package does not free() anything else than what
  31. **    it has itself allocated.
  32. **
  33. ** AUTHORS:
  34. **    AL    Ari Luotonen    luotonen@dxcern.cern.ch
  35. **
  36. ** HISTORY:
  37. **
  38. **
  39. ** BUGS:
  40. **
  41. **
  42. */
  43.  
  44. #include <stdio.h>        /* FILE */
  45. #include <string.h>        /* strchr() */
  46.  
  47. #include "HTUtils.h"
  48. #include "HTString.h"
  49. #include "HTAccess.h"        /* HTSecure            */
  50. #include "HTFile.h"        /* HTLocalName            */
  51. #include "HTRules.h"        /*                 */
  52. #include "HTParse.h"        /* URL parsing function        */
  53. #include "HTList.h"        /* HTList object        */
  54.  
  55. #include "HTAAUtil.h"        /* AA common parts        */
  56. #include "HTAuth.h"        /* Authentication        */
  57. #include "HTACL.h"        /* Access Control List        */
  58. #include "HTGroup.h"        /* Group handling        */
  59. #include "HTAAProt.h"        /* Protection file parsing    */
  60. #include "HTAAServ.h"        /* Implemented here        */
  61.  
  62.  
  63.  
  64. /*
  65. ** Global variables
  66. */
  67. PUBLIC time_t theTime;
  68.  
  69.  
  70. /*
  71. ** Module-wide global variables
  72. */
  73. PRIVATE FILE *  htaa_logfile        = NULL;         /* Log file          */
  74. PRIVATE HTAAUser *htaa_user = NULL;            /* Authenticated user */
  75. PRIVATE HTAAFailReasonType HTAAFailReason = HTAA_OK;    /* AA fail reason     */
  76.  
  77.  
  78.  
  79. /* SERVER PUBLIC                    HTAA_statusMessage()
  80. **        RETURN A STRING EXPLAINING ACCESS
  81. **        AUTHORIZATION FAILURE
  82. **        (Can be used in server reply status line
  83. **         with 401/403 replies.)
  84. ** ON EXIT:
  85. **    returns    a string containing the error message
  86. **        corresponding to internal HTAAFailReason.
  87. */
  88. PUBLIC char *HTAA_statusMessage NOARGS
  89. {
  90.     switch (HTAAFailReason) {
  91.  
  92.     /* 401 cases */
  93.       case HTAA_NO_AUTH:
  94.     return "Unauthorized -- authentication failed";
  95.     break;
  96.       case HTAA_NOT_MEMBER:
  97.     return "Unauthorized to access the document";
  98.     break;
  99.  
  100.     /* 403 cases */
  101.       case HTAA_BY_RULE:
  102.     return "Forbidden -- by rule";
  103.     break;
  104.       case HTAA_IP_MASK:
  105.     return "Forbidden -- server refuses to serve to your IP address";
  106.     break;
  107.       case HTAA_NO_ACL:
  108.       case HTAA_NO_ENTRY:
  109.     return "Forbidden -- access to file is never allowed";
  110.     break;
  111.       case HTAA_SETUP_ERROR:
  112.     return "Forbidden -- server protection setup error";
  113.     break;
  114.  
  115.     /* 404 cases */
  116.       case HTAA_NOT_FOUND:
  117.     return "Not found -- file doesn't exist or is read protected";
  118.     break;
  119.  
  120.     /* Success */
  121.       case HTAA_OK:
  122.     return "AA: Access should be ok but something went wrong"; 
  123.     break;
  124.  
  125.     /* Others */
  126.       default:
  127.     return "Access denied -- unable to specify reason (bug)";
  128.  
  129.     } /* switch */
  130. }
  131.  
  132.  
  133.  
  134. PRIVATE char *status_name ARGS1(HTAAFailReasonType, reason)
  135. {
  136.     switch (HTAAFailReason) {
  137.  
  138.     /* 401 cases */
  139.       case HTAA_NO_AUTH:
  140.     return "NO-AUTHENTICATION";
  141.     break;
  142.       case HTAA_NOT_MEMBER:
  143.     return "NOT-AUTHORIZED";
  144.     break;
  145.  
  146.     /* 403 cases */
  147.       case HTAA_BY_RULE:
  148.     return "FORB-RULE";
  149.     break;
  150.       case HTAA_IP_MASK:
  151.     return "FORB-IP";
  152.     break;
  153.       case HTAA_NO_ACL:
  154.     return "NO-ACL-FILE";
  155.     break;
  156.       case HTAA_NO_ENTRY:
  157.     return "NO-ACL-ENTRY";
  158.     break;
  159.       case HTAA_SETUP_ERROR:
  160.     return "SETUP-ERROR";
  161.     break;
  162.  
  163.     /* 404 cases */
  164.       case HTAA_NOT_FOUND:
  165.     return "NOT-FOUND";
  166.     break;
  167.  
  168.     /* Success */
  169.       case HTAA_OK:
  170.     return "OK";
  171.     break;
  172.  
  173.     /* Others */
  174.       default:
  175.     return "SERVER-BUG";
  176.     } /* switch */
  177. }
  178.  
  179.     
  180.  
  181.  
  182.  
  183.  
  184. /* PRIVATE                        check_uthorization()
  185. **        CHECK IF USER IS AUTHORIZED TO ACCESS A FILE
  186. ** ON ENTRY:
  187. **    pathname    is the physical file pathname
  188. **            to access.
  189. **    method        method, e.g. METHOD_GET, METHOD_PUT, ...
  190. **    scheme        authentication scheme.
  191. **    scheme_specifics authentication string (or other
  192. **            scheme specific parameters, like
  193. **            Kerberos-ticket).
  194. **
  195. ** ON EXIT:
  196. **    returns        HTAA_OK on success.
  197. **            Otherwise the reason for failing.
  198. ** NOTE:
  199. **    This function does not check whether the file
  200. **    exists or not -- so the status  404 Not found
  201. **    must be returned from somewhere else (this is
  202. **    to avoid unnecessary overhead of opening the
  203. **    file twice).
  204. */
  205. PRIVATE HTAAFailReasonType check_authorization ARGS4(CONST char *,  pathname,
  206.                              HTAAMethod,    method,
  207.                              HTAAScheme,    scheme,
  208.                              char *, scheme_specifics)
  209. {
  210.     HTAAFailReasonType reason;
  211.     GroupDef *allowed_groups;
  212.     FILE *acl_file = NULL;
  213.     HTAAProt *prot = NULL;    /* Protection mode */
  214.  
  215.     htaa_user = NULL;
  216.  
  217.     if (!pathname) {
  218.     if (TRACE) fprintf(stderr,
  219.                "HTAA_checkAuthorization: Forbidden by rule\n");
  220.     return HTAA_BY_RULE;
  221.     }
  222.     if (TRACE) fprintf(stderr, "%s `%s' %s %s\n",
  223.                "HTAA_checkAuthorization: translated path:",
  224.                pathname, "method:", HTAAMethod_name(method));
  225.  
  226.     /*
  227.     ** Get protection setting (set up by callbacks from rule system)
  228.     ** NULL, if not protected by a "protect" rule.
  229.     */
  230.     prot = HTAA_getCurrentProtection();
  231.  
  232.     /*
  233.     ** Check ACL existence
  234.     */
  235.     if (!(acl_file = HTAA_openAcl(pathname))) {
  236.     if (prot) { /* protect rule, but no ACL */
  237.         if (prot->mask_group) {
  238.         /*
  239.         ** Only mask enabled, check that
  240.         */
  241.         GroupDefList *group_def_list =
  242.             HTAA_readGroupFile(HTAssocList_lookup(prot->values,
  243.                               "group"));
  244.         /*
  245.         ** Authenticate if authentication info given
  246.         */
  247.         if (scheme != HTAA_UNKNOWN  &&  scheme != HTAA_NONE) {
  248.             htaa_user = HTAA_authenticate(scheme,
  249.                           scheme_specifics,
  250.                           prot);
  251.             if (TRACE) fprintf(stderr, "Authentication returned: %s\n",
  252.                        (htaa_user ? htaa_user->username
  253.                               : "NOT-AUTHENTICATED"));
  254.         }
  255.         HTAA_resolveGroupReferences(prot->mask_group, group_def_list);
  256.         reason = HTAA_userAndInetInGroup(prot->mask_group,
  257.                          htaa_user
  258.                           ? htaa_user->username : "",
  259.                          HTClientHost,
  260.                          NULL);
  261.         if (TRACE) {
  262.             if (reason != HTAA_OK)
  263.             fprintf(stderr, "%s %s %s %s\n",
  264.                 "HTAA_checkAuthorization: access denied",
  265.                 "by mask (no ACL, only Protect rule)",
  266.                 "host", HTClientHost);
  267.             else fprintf(stderr, "%s %s %s %s\n",
  268.                  "HTAA_checkAuthorization: request from",
  269.                  HTClientHost, 
  270.                  "accepted by only mask match (no ACL, only",
  271.                  "Protect rule, and only mask enabled)");
  272.         }
  273.         return reason;
  274.         }
  275.         else {    /* 403 Forbidden */
  276.         if (TRACE) fprintf(stderr, "%s %s\n",
  277.                    "HTAA_checkAuthorization: Protected, but",
  278.                    "no mask group nor ACL -- forbidden");
  279.         return HTAA_NO_ACL;
  280.         }
  281.     }
  282.     else { /* No protect rule and no ACL => OK 200 */
  283.         if (TRACE) fprintf(stderr, "HTAA_checkAuthorization: %s\n",
  284.                    "no protect rule nor ACL -- ok\n");
  285.         return HTAA_OK;
  286.     }
  287.     }
  288.  
  289.     /*
  290.     ** Now we know that ACL exists
  291.     */
  292.     if (!prot) {        /* Not protected by "protect" rule */
  293.     if (TRACE) fprintf(stderr,
  294.                "HTAA_checkAuthorization: default protection\n");
  295.     prot = HTAA_getDefaultProtection();   /* Also sets current protection */
  296.  
  297.     if (!prot) {        /* @@ Default protection not set ?? */
  298.         if (TRACE) fprintf(stderr, "%s %s\n",
  299.                    "HTAA_checkAuthorization: default protection",
  300.                    "not set (internal server error)!!");
  301.         return HTAA_SETUP_ERROR;
  302.     }
  303.     }
  304.  
  305.     /*
  306.     ** Now we know that document is protected and ACL exists.
  307.     ** Check against ACL entry.
  308.     */
  309.     {
  310.     GroupDefList *group_def_list =
  311.         HTAA_readGroupFile(HTAssocList_lookup(prot->values, "group"));
  312.  
  313.     /*
  314.     ** Authenticate now that we know protection mode
  315.     */
  316.     if (scheme != HTAA_UNKNOWN  &&  scheme != HTAA_NONE) {
  317.         htaa_user = HTAA_authenticate(scheme,
  318.                       scheme_specifics,
  319.                       prot);
  320.         if (TRACE) fprintf(stderr, "Authentication returned: %s\n",
  321.                    (htaa_user
  322.                 ? htaa_user->username : "NOT-AUTHENTICATED"));
  323.     }
  324.     /* 
  325.     ** Check mask group
  326.     */
  327.     if (prot->mask_group) {
  328.         HTAA_resolveGroupReferences(prot->mask_group, group_def_list);
  329.         reason=HTAA_userAndInetInGroup(prot->mask_group,
  330.                        htaa_user ? htaa_user->username : "",
  331.                        HTClientHost,
  332.                        NULL);
  333.         if (reason != HTAA_OK) {
  334.         if (TRACE) fprintf(stderr, "%s %s %s\n",
  335.                    "HTAA_checkAuthorization: access denied",
  336.                    "by mask, host:", HTClientHost);
  337.         return reason;
  338.         }
  339.         else {
  340.         if (TRACE) fprintf(stderr, "%s %s %s %s %s\n",
  341.                    "HTAA_checkAuthorization: request from",
  342.                    HTClientHost, 
  343.                    "accepted by just mask group match",
  344.                    "(no ACL, only Protect rule, and only",
  345.                    "mask enabled)");
  346.         /* And continue authorization checking */
  347.         }
  348.     }
  349.     /*
  350.         ** Get ACL entries; get first one first, the loop others
  351.     ** Remember, allowed_groups is automatically freed by
  352.     ** HTAA_getAclEntry().
  353.     */
  354.     allowed_groups = HTAA_getAclEntry(acl_file, pathname, method);
  355.     if (!allowed_groups) {
  356.         if (TRACE) fprintf(stderr, "%s `%s' %s\n",
  357.                    "No entry for file", pathname, "in ACL");
  358.         HTAA_closeAcl(acl_file);
  359.         return HTAA_NO_ENTRY;    /* Forbidden -- no entry in the ACL */
  360.     }
  361.     else {
  362.         do {
  363.         HTAA_resolveGroupReferences(allowed_groups, group_def_list);
  364.         reason = HTAA_userAndInetInGroup(allowed_groups,
  365.                          htaa_user
  366.                          ? htaa_user->username : "",
  367.                          HTClientHost,
  368.                          NULL);
  369.         if (reason == HTAA_OK) {
  370.             HTAA_closeAcl(acl_file);
  371.             return HTAA_OK;    /* OK */
  372.         }
  373.         allowed_groups = HTAA_getAclEntry(acl_file, pathname, method);
  374.         } while (allowed_groups);
  375.         HTAA_closeAcl(acl_file);
  376.         return HTAA_NOT_MEMBER;    /* Unauthorized */
  377.     }
  378.     }
  379. }
  380.  
  381.  
  382.  
  383. /* PUBLIC                          HTAA_checkAuthorization()
  384. **        CHECK IF USER IS AUTHORIZED TO ACCESS A FILE
  385. ** ON ENTRY:
  386. **    url        is the document to be accessed.
  387. **    method_name    name of the method, e.g. "GET"
  388. **    scheme_name    authentication scheme name.
  389. **    scheme_specifics authentication string (or other
  390. **            scheme specific parameters, like
  391. **            Kerberos-ticket).
  392. **
  393. ** ON EXIT:
  394. **    returns    status codes uniform with those of HTTP:
  395. **      200 OK       if file access is ok.
  396. **      401 Unauthorized if user is not authorized to
  397. **               access the file.
  398. **      403 Forbidden       if there is no entry for the
  399. **               requested file in the ACL.
  400. **
  401. ** NOTE:
  402. **    This function does not check whether the file
  403. **    exists or not -- so the status  404 Not found
  404. **    must be returned from somewhere else (this is
  405. **    to avoid unnecessary overhead of opening the
  406. **    file twice).
  407. **
  408. */
  409. PUBLIC int HTAA_checkAuthorization ARGS4(CONST char *,    url,
  410.                      CONST char *,    method_name,
  411.                      CONST char *,    scheme_name,
  412.                                          char *,    scheme_specifics)
  413. {
  414.     static char *pathname = NULL;
  415.     char *local_copy = NULL;
  416.     HTAAMethod method = HTAAMethod_enum(method_name);
  417.     HTAAScheme scheme = HTAAScheme_enum(scheme_name);
  418.     
  419.     /*
  420.     ** Translate into absolute pathname, and
  421.     ** check for "protect" and "defprot" rules.
  422.     */
  423.     FREE(pathname);        /* From previous call    */
  424.     StrAllocCopy(local_copy, url);
  425.     {
  426.     char *keywords = strchr(local_copy, '?');
  427.     if (keywords) *keywords = (char)0;    /* Chop off keywords */
  428.     }
  429.     HTSimplify(local_copy);    /* Remove ".." etc. */
  430.     pathname = HTTranslate(local_copy);
  431.     if (!HTSecure) {
  432.     char *localname = HTLocalName(pathname);
  433.     free(pathname);
  434.     pathname = localname;
  435.     }        
  436.     FREE(local_copy);
  437.  
  438.     HTAAFailReason = check_authorization(pathname, method,
  439.                      scheme, scheme_specifics);
  440.  
  441.     if (htaa_logfile) {
  442.     time(&theTime);
  443.     fprintf(htaa_logfile, "%24.24s %s %s %s %s %s\n",
  444.         ctime(&theTime),
  445.         HTClientHost ? HTClientHost : "local",
  446.         method_name,
  447.         url,
  448.         status_name(HTAAFailReason),
  449.         htaa_user && htaa_user->username
  450.         ? htaa_user->username : "");
  451.     fflush(htaa_logfile);    /* Actually update it on disk */
  452.     if (TRACE) fprintf(stderr, "Log: %24.24s %s %s %s %s %s\n",
  453.                ctime(&theTime),
  454.                HTClientHost ? HTClientHost : "local",
  455.                method_name,
  456.                url,
  457.                status_name(HTAAFailReason),
  458.                htaa_user && htaa_user->username
  459.                ? htaa_user->username : "");
  460.     }
  461.  
  462.     switch (HTAAFailReason) {
  463.  
  464.       case HTAA_NO_AUTH:
  465.       case HTAA_NOT_MEMBER:
  466.     return 401;
  467.     break;
  468.  
  469.       case HTAA_BY_RULE:
  470.       case HTAA_IP_MASK:
  471.       case HTAA_NO_ACL:
  472.       case HTAA_NO_ENTRY:
  473.       case HTAA_SETUP_ERROR:
  474.     return 403;
  475.     break;
  476.  
  477.       case HTAA_NOT_FOUND:
  478.     return 404;
  479.     break;
  480.  
  481.       case HTAA_OK:
  482.     return 200;
  483.     break;
  484.  
  485.       default:
  486.     return 500;
  487.     } /* switch */
  488. }
  489.  
  490.  
  491.  
  492.  
  493.  
  494. /* PRIVATE                    compose_scheme_specifics()
  495. **        COMPOSE SCHEME-SPECIFIC PARAMETERS
  496. **        TO BE SENT ALONG WITH SERVER REPLY
  497. **        IN THE WWW-Authenticate: FIELD.
  498. ** ON ENTRY:
  499. **    scheme        is the authentication scheme for which
  500. **            parameters are asked for.
  501. **    prot        protection setup structure.
  502. **
  503. ** ON EXIT:
  504. **    returns        scheme specific parameters in an
  505. **            auto-freed string.
  506. */
  507. PRIVATE char *compose_scheme_specifics ARGS2(HTAAScheme,    scheme,
  508.                          HTAAProt *,    prot)
  509. {
  510.     static char *result = NULL;
  511.  
  512.     FREE(result);    /* From previous call */
  513.  
  514.     switch (scheme) {
  515.       case HTAA_BASIC:
  516.     {
  517.         char *realm = HTAssocList_lookup(prot->values, "server");
  518.         result = (char*)malloc(60);
  519.         sprintf(result, "realm=\"%s\"",
  520.             (realm ? realm : "UNKNOWN"));
  521.         return result;
  522.     }
  523.     break;
  524.  
  525.       case HTAA_PUBKEY:
  526.     {
  527.         char *realm = HTAssocList_lookup(prot->values, "server");
  528.         result = (char*)malloc(200);
  529.         sprintf(result, "realm=\"%s\", key=\"%s\"",
  530.             (realm ? realm : "UNKNOWN"),
  531.             "PUBKEY-NOT-IMPLEMENTED");
  532.         return result;
  533.     }
  534.     break;
  535.       default:
  536.     return NULL;
  537.     }
  538. }
  539.  
  540.  
  541. /* SERVER PUBLIC                    HTAA_composeAuthHeaders()
  542. **        COMPOSE WWW-Authenticate: HEADER LINES
  543. **        INDICATING VALID AUTHENTICATION SCHEMES
  544. **        FOR THE REQUESTED DOCUMENT
  545. ** ON ENTRY:
  546. **    No parameters, but HTAA_checkAuthorization() must
  547. **    just before have failed because a wrong (or none)
  548. **    authentication scheme was used.
  549. **
  550. ** ON EXIT:
  551. **    returns    a buffer containing all the WWW-Authenticate:
  552. **        fields including CRLFs (this buffer is auto-freed).
  553. **        NULL, if authentication won't help in accessing
  554. **        the requested document.
  555. **
  556. */
  557. PUBLIC char *HTAA_composeAuthHeaders NOARGS
  558. {
  559.     static char *result = NULL;
  560.     HTAAScheme scheme;
  561.     char *scheme_name;
  562.     char *scheme_params;
  563.     HTAAProt *prot = HTAA_getCurrentProtection();
  564.  
  565.     if (!prot) {
  566.     if (TRACE) fprintf(stderr, "%s %s\n",
  567.                "HTAA_composeAuthHeaders: Document not protected",
  568.                "-- why was this function called??");
  569.     return NULL;
  570.     }
  571.     else if (TRACE) fprintf(stderr, "HTAA_composeAuthHeaders: for file `%s'\n",
  572.                 prot->filename);
  573.  
  574.     FREE(result);    /* From previous call */
  575.     if (!(result = (char*)malloc(4096)))    /* @@ */
  576.     outofmem(__FILE__, "HTAA_composeAuthHeaders");
  577.     *result = (char)0;
  578.  
  579.     for (scheme=0; scheme < HTAA_MAX_SCHEMES; scheme++) {
  580.     if (-1 < HTList_indexOf(prot->valid_schemes, (void*)scheme)) {
  581.         if ((scheme_name = HTAAScheme_name(scheme))) {
  582.         scheme_params = compose_scheme_specifics(scheme,prot);
  583.         strcat(result, "WWW-Authenticate: ");
  584.         strcat(result, scheme_name);
  585.         if (scheme_params) {
  586.             strcat(result, " ");
  587.             strcat(result, scheme_params);
  588.         }
  589.         strcat(result, "\r\n");
  590.         } /* scheme name found */
  591.         else if (TRACE) fprintf(stderr, "HTAA_composeAuthHeaders: %s %d\n",
  592.                     "No name found for scheme number", scheme);
  593.     } /* scheme valid for requested document */
  594.     } /* for every scheme */
  595.     
  596.     return result;
  597. }
  598.  
  599.  
  600.  
  601. /* PUBLIC                        HTAA_startLogging()
  602. **        START UP ACCESS AUTHORIZATION LOGGING
  603. ** ON ENTRY:
  604. **    fp    is the open log file.
  605. **
  606. */
  607. PUBLIC void HTAA_startLogging ARGS1(FILE *, fp)
  608. {
  609.     htaa_logfile = fp;
  610. }
  611.  
  612.